﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Input;
using System.Xml.Linq;
using c2iGMailNotifier.Messaging;
using c2iGMailNotifier.Model;
using c2iGMailNotifier.Service;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;

namespace c2iGMailNotifier.ViewModel
{
    public class OptionsViewModel : ViewModelBase
    {
        public OptionsViewModel()
        {
            if (IsInDesignMode)
            {
                this.User = new User() { Password = "MyPassword", UserName = "c2i" };
                this.c2iGmailNotifierInformation = new ReleaseInformation(){Version="1.0.0.1", Url="http://www.c2i.fr/c2iGmailNotifier/"};
            }
            else
            {
                this.User = SettingsReaderWriter.GetCurrentUser();
                CreateSaveSettingsCommand();
                CreateCheckVersionCommand();
                CreateNavigateCommand();
                this.backgroundWorker = new BackgroundWorker();
                this.backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
                this.backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);

                Messenger.Default.Register(this, (CheckVersionMessage message) => this.ExecuteCheckVersionCommand());
            }
            this.Version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
        }

        #region Fields
        private const string UpdatesUrl = "http://www.c2i.fr/c2iGMailNotifier/ReleaseInformation";
        private BackgroundWorker backgroundWorker;
        #endregion

        #region Properties

        #region IsNewVersionAvailable Property

        /// <summary>
        /// The <see cref="IsNewVersionAvailable" /> property's name.
        /// </summary>
        public const string IsNewVersionAvailablePropertyName = "IsNewVersionAvailable";

        private bool _isNewVersionAvailable;

        public bool IsNewVersionAvailable
        {
            get { return this._isNewVersionAvailable; }

            private set
            {
                if (this._isNewVersionAvailable == value) return;

                this._isNewVersionAvailable = value;
                RaisePropertyChanged(IsNewVersionAvailablePropertyName);
            }
        }

        #endregion

        #region User Property

        /// <summary>
        /// The <see cref="User" /> property's name.
        /// </summary>
        public const string UserPropertyName = "User";

        private User _user;

        public User User
        {
            get { return this._user; }

            private set
            {
                if (this._user == value) return;

                this._user = value;
                RaisePropertyChanged(UserPropertyName);
            }
        }

        #endregion

        #region Version Property

        /// <summary>
        /// The <see cref="Version" /> property's name.
        /// </summary>
        public const string VersionPropertyName = "Version";

        private string _version;

        public string Version
        {
            get { return this._version; }

            private set
            {
                if (this._version == value) return;

                this._version = value;
                RaisePropertyChanged(VersionPropertyName);
            }
        }

        #endregion

        #region c2iGmailNotifierInformation Property

        /// <summary>
        /// The <see cref="c2iGmailNotifierInformation" /> property's name.
        /// </summary>
        public const string c2iGmailNotifierInformationPropertyName = "c2iGmailNotifierInformation";

        private ReleaseInformation _c2iGmailNotifierInformation;

        public ReleaseInformation c2iGmailNotifierInformation
        {
            get { return this._c2iGmailNotifierInformation; }

            private set
            {
                if (this._c2iGmailNotifierInformation == value) return;

                this._c2iGmailNotifierInformation = value;
                RaisePropertyChanged(c2iGmailNotifierInformationPropertyName);
            }
        }

        #endregion       
        #endregion        

        #region Commands
        #region CheckVersionCommand

        private void CreateCheckVersionCommand()
        {
            CheckVersionCommand = new RelayCommand(ExecuteCheckVersionCommand, CanExecuteCheckVersionCommand);
        }

        public ICommand CheckVersionCommand { get; internal set; }
 
        public void ExecuteCheckVersionCommand()
        {
            if (!CanExecuteCheckVersionCommand())
                return;

            backgroundWorker.RunWorkerAsync();
        }

        public bool CanExecuteCheckVersionCommand()
        {
            return !backgroundWorker.IsBusy;
        }

        #endregion
        
        #region NavigateCommand

        private void CreateNavigateCommand()
        {
            NavigateCommand = new RelayCommand<string>(ExecuteNavigateCommand, CanExecuteNavigateCommand);
        }

        public ICommand NavigateCommand { get; internal set; }


        public void ExecuteNavigateCommand(string argument)
        {
            if (!string.IsNullOrEmpty(argument))
                System.Diagnostics.Process.Start(argument);
        }

        public bool CanExecuteNavigateCommand(string argument)
        {
            return !string.IsNullOrEmpty(argument);
        }

        #endregion

        #region SaveSettingsCommand

        private void CreateSaveSettingsCommand()
        {
            SaveSettingsCommand = new RelayCommand(ExecuteSaveSettingsCommand);
        }

        public ICommand SaveSettingsCommand { get; internal set; }

        public void ExecuteSaveSettingsCommand()
        {
            SettingsReaderWriter.SetCurrentUser(this.User);
            Messenger.Default.Send(new UserSettingsChanged(this));
            Messenger.Default.Send(new ShowViewMessage(this) {ViewKey="EmailsListView"});
        }

        public bool CanExecuteSaveSettingsCommand()
        {
            return this.User != null;
        }

        #endregion
        #endregion

        #region private Methods
        void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                this.c2iGmailNotifierInformation = null;
            }
            else
            {
                this.c2iGmailNotifierInformation = e.Result as ReleaseInformation;
                this.IsNewVersionAvailable = this.c2iGmailNotifierInformation.Version != this.Version;
                if (this.IsNewVersionAvailable)
                    Messenger.Default.Send(new ShowViewMessage(this) { ViewKey = "OptionsView" });
            }
        }

        void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            XDocument doc = XDocument.Load(UpdatesUrl);
            if (doc.Root != null && doc.Root.Element("ReleaseInformation") != null)
            {
                XElement releaseElement = doc.Root.Element("ReleaseInformation");
                ReleaseInformation result = new ReleaseInformation()
                                                {
                                                    PublishDate =
                                                        DateTime.Parse(releaseElement.Element("PublishDate").Value,
                                                                       CultureInfo.InvariantCulture),
                                                    Version = releaseElement.Element("Version").Value,
                                                    Url = releaseElement.Element("Url").Value,
                                                    Description = releaseElement.Element("Description").Value
                                                };

                e.Result = result;
            }
        }
        #endregion

    }
}